﻿/* 
* Copyright (c) 2010, The University of Texas at Austin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, 
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, 
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, 
* this list of conditions and the following disclaimer in the documentation and/or other materials 
* provided with the distribution.
*
* Neither the name of The University of Texas at Austin nor the names of its contributors may be 
* used to endorse or promote products derived from this software without specific prior written 
* permission.
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

using System.Diagnostics;
using System.Windows;
using System.Windows.Media;
using Bio.Data;
using Bio.Data.Interfaces;

namespace Bio.Views.Structure.Editor.Internal.Rendering.Visuals
{
    public class BasePairStructureElementVisualComponentFactory
    {
        public static BasePairStructureElementVisualComponent Create(IBasePairBioEntity basePair)
        {
            Debug.Assert(basePair != null);
            IExtensibleProperties properties = basePair as IExtensibleProperties;
            
            if (properties != null)
            {
                if (properties.DoesExtendedPropertyExist(BasePairMetadata.Key))
                {
                    BasePairMetadata metadata = properties.GetExtendedProperty<BasePairMetadata>(BasePairMetadata.Key);
                    BasePairStructureElementVisualComponent bpVisual = null;

                    if (metadata != null &&
                       (metadata.ConnectorStyle.HasValue ||
                        metadata.ConnectorRendering != null ||
                        metadata.ConnectorVisible.HasValue ||
                        metadata.NucleotideRenderingProperties != null))
                    {
                        if (metadata.ConnectorStyle.HasValue)
                        {
                            if (bpVisual == null)
                                bpVisual = new BasePairStructureElementVisualComponent(basePair);
                            switch (metadata.ConnectorStyle.Value)
                            {
                                case BasePairMetadata.ConnectorRenderingMode.Circle:
                                    bpVisual.BasePairConnectorRenderingStyle = BasePairConnectorRenderingMode.Circle;
                                    break;
                                case BasePairMetadata.ConnectorRenderingMode.Line:
                                    bpVisual.BasePairConnectorRenderingStyle = BasePairConnectorRenderingMode.Line;
                                    break;
                                case BasePairMetadata.ConnectorRenderingMode.Rectangle:
                                    bpVisual.BasePairConnectorRenderingStyle = BasePairConnectorRenderingMode.Rectangle;
                                    break;
                                default:
                                    bpVisual.BasePairConnectorRenderingStyle = null;
                                    break;
                            }
                        }

                        if (metadata.ConnectorVisible.HasValue)
                        {
                            if (bpVisual == null)
                                bpVisual = new BasePairStructureElementVisualComponent(basePair);

                            bpVisual.BasePairConnectorIsVisible = metadata.ConnectorVisible;
                        }

                        if (metadata.ConnectorRendering != null)
                        {
                            if (bpVisual == null)
                                bpVisual = new BasePairStructureElementVisualComponent(basePair);

                            if (metadata.ConnectorRendering.FillColor != null)
                            {
                                try { bpVisual.BasePairConnectorFill = new SolidColorBrush((Color)colorChecker.ConvertFrom(metadata.ConnectorRendering.FillColor)); }
                                catch { }
                            }

                            if (metadata.ConnectorRendering.Size > 0.0)
                                bpVisual.BasePairConnectorSize = metadata.ConnectorRendering.Size;

                            if (metadata.ConnectorRendering.EdgeThickness > 0.0)
                                bpVisual.BasePairConnectorStrokeThickness = metadata.ConnectorRendering.EdgeThickness;

                            if (metadata.ConnectorRendering.StrokeColor != null)
                            {
                                try { bpVisual.BasePairConnectorStroke = new SolidColorBrush((Color)colorChecker.ConvertFrom(metadata.ConnectorRendering.StrokeColor)); }
                                catch { }
                            }

                            bpVisual.BasePairConnectorIsFilled = metadata.ConnectorRendering.Filled;
                        }

                        if (metadata.NucleotideRenderingProperties != null)
                        {
                            if (bpVisual == null)
                                bpVisual = new BasePairStructureElementVisualComponent(basePair);

                            if (metadata.NucleotideRenderingProperties.Style.HasValue && metadata.NucleotideRenderingProperties.Style.Value == NucleotideMetadata.RenderingMode.Text)
                                bpVisual.NucleotideRenderingStyle = NucleotideRenderingMode.Text;
                            else if (metadata.NucleotideRenderingProperties.Style.HasValue && metadata.NucleotideRenderingProperties.Style.Value == NucleotideMetadata.RenderingMode.Circle)
                                bpVisual.NucleotideRenderingStyle = NucleotideRenderingMode.Circle;

                            if (metadata.NucleotideRenderingProperties.TextRendering != null)
                            {
                                //Lets see if we have valid values for any specified properties (the built in defaults are set, so if any fail we can skip them).
                                if (metadata.NucleotideRenderingProperties.TextRendering.Font != null)
                                {
                                    try { bpVisual.NucleotideFontFamily = (FontFamily)fontFamilyChecker.ConvertFrom(metadata.NucleotideRenderingProperties.TextRendering.Font); }
                                    catch { }
                                }

                                if (metadata.NucleotideRenderingProperties.TextRendering.Color != null)
                                {
                                    try { bpVisual.NucleotideFill = new SolidColorBrush((Color)colorChecker.ConvertFrom(metadata.NucleotideRenderingProperties.TextRendering.Color)); }
                                    catch { }
                                }

                                if (metadata.NucleotideRenderingProperties.TextRendering.FontStyle != null)
                                {
                                    try { bpVisual.NucleotideFontStyle = (FontStyle)fontStyleChecker.ConvertFrom(metadata.NucleotideRenderingProperties.TextRendering.FontStyle); }
                                    catch { }
                                }

                                if (metadata.NucleotideRenderingProperties.TextRendering.FontWeight != null)
                                {
                                    try { bpVisual.NucleotideFontWeight = (FontWeight)fontWeightChecker.ConvertFrom(metadata.NucleotideRenderingProperties.TextRendering.FontWeight); }
                                    catch { }
                                }

                                if (metadata.NucleotideRenderingProperties.TextRendering.FontSize > 0.0)
                                    bpVisual.NucleotideFontSize = metadata.NucleotideRenderingProperties.TextRendering.FontSize;

                                if (metadata.NucleotideRenderingProperties.IsSubstituted)
                                {
                                    bpVisual.IsNucleotideSubstituted = true;
                                    bpVisual.NucleotideSubstitution = metadata.NucleotideRenderingProperties.SubstitutionCharacter;
                                }
                            }

                            if (metadata.NucleotideRenderingProperties.CircleRendering != null)
                            {
                                if (metadata.NucleotideRenderingProperties.CircleRendering.Diameter > 0.0)
                                    bpVisual.NucleotideCircleDiameter = metadata.NucleotideRenderingProperties.CircleRendering.Diameter;

                                if (metadata.NucleotideRenderingProperties.CircleRendering.EdgeThickness > 0.0)
                                    bpVisual.NucleotideCircleEdgeThickness = metadata.NucleotideRenderingProperties.CircleRendering.EdgeThickness;

                                if (metadata.NucleotideRenderingProperties.CircleRendering.FillColor != null)
                                {
                                    try { bpVisual.NucleotideCircleFill = new SolidColorBrush((Color)colorChecker.ConvertFrom(metadata.NucleotideRenderingProperties.CircleRendering.FillColor)); }
                                    catch { }
                                }

                                if (metadata.NucleotideRenderingProperties.CircleRendering.EdgeColor != null)
                                {
                                    try { bpVisual.NucleotideCircleStroke = new SolidColorBrush((Color)colorChecker.ConvertFrom(metadata.NucleotideRenderingProperties.CircleRendering.EdgeColor)); }
                                    catch { }
                                }

                                bpVisual.NucleotideCircleIsFilled = metadata.NucleotideRenderingProperties.CircleRendering.Filled;
                            }
                        }
                    }
                    else { goto DefaultRendering; }

                    return bpVisual;
                }
                else { goto DefaultRendering; }
            }
            else { goto DefaultRendering; }

            DefaultRendering:
            //If we reach here, were picking up the rendering from either a parent (helix or the global structure model), accepting any defaults.
            BasePairStructureElementVisualComponent defaultBPVisual = new BasePairStructureElementVisualComponent(basePair);
            return defaultBPVisual;
        }

        private static readonly FontFamilyConverter fontFamilyChecker = new FontFamilyConverter();
        private static readonly FontWeightConverter fontWeightChecker = new FontWeightConverter();
        private static readonly FontStyleConverter fontStyleChecker = new FontStyleConverter();
        private static readonly ColorConverter colorChecker = new ColorConverter();
    }
}
